﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Willows.Model
{
	public partial class QueueConnectorWriterInterface
		: QueueWriterInterface, IQueueConnectorWriter
	{
		private Weazel.Willows.RefinedModel.OutPort dataOutPort;
		public Weazel.Willows.RefinedModel.OutPort DataOutPort
		{
			get { return dataOutPort; }			
		}

		private Weazel.Willows.RefinedModel.InPort canWritePort;
		public Weazel.Willows.RefinedModel.InPort CanWritePort
		{
			get { return canWritePort; }			
		}

		private Weazel.Willows.RefinedModel.OutPort doWritePort;
		public Weazel.Willows.RefinedModel.OutPort DoWritePort
		{
			get { return doWritePort; }		
		}

		#region Signal/Port Insertion
		private void insertDataOutPort(RefinedModel.Datapath datapath)
		{
			dataOutPort =
				new Weazel.Willows.RefinedModel.OutPort(TypeRegistry, datapath, EnqueueSignalName, Type);

			datapath.OutPorts.Add(dataOutPort.LocalName, dataOutPort);
		}

		private void insertCanWritePort(RefinedModel.Datapath datapath)
		{
			canWritePort =
				new Weazel.Willows.RefinedModel.InPort(TypeRegistry, datapath, CanWriteSignalName, (Type)TypeRegistry["boolean"]);

			datapath.InPorts.Add(canWritePort.LocalName, canWritePort);
		}

		private void insertDoWritePort(RefinedModel.Datapath datapath)
		{
			doWritePort =
				new Weazel.Willows.RefinedModel.OutPort(TypeRegistry, datapath, DoWriteSignalName, (Type)TypeRegistry["boolean"]);

			datapath.OutPorts.Add(doWritePort.LocalName, doWritePort);
		}
		#endregion

		public override void Refine(RefinedModel.Model model)
		{
			if (this.writer == null)
			{
				string message = 
					string.Format("Internal error: no writer bound to queue writer connector '{0}' in module '{1}'", 
						Name,
						Parent.Name
					);

				throw new NullReferenceException(message);
			}

			if (Parent is Module)
			{
				// parent must be module, cast
				Module module = Parent as Module;

				// refine the module (if needed)
				module.Refine(model);

				// get a reference to it's datapath
				RefinedModel.Datapath datapath = module.Datapath;

				insertCanWritePort(datapath);
				insertDoWritePort(datapath);
				insertDataOutPort(datapath);
			}
			else
			{
				string message =
					string.Format("Refine(): Unexpected parent Type '{0}'. Expected 'Datapath'.",
					Parent.GetType().ToString());

				throw new NotSupportedException(message);
			}

			writer.Refine(model);
		}
	}
}
